package com.zhanglinwei.openApiServer;

import com.zhanglinwei.openApiClient.model.entity.CodefyTools;
import com.zhanglinwei.openApiClient.wrapper.OpenApiLambdaWrapper;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;

public class SQLWrapperTest {
    public static void main(String[] args) {
        // 1. 基础条件方法测试
        System.out.println("=== 等值查询 ===");
        System.out.println(testEQ().previewSql());

        System.out.println("\n=== 不等查询 ===");
        System.out.println(testNE().previewSql());

        System.out.println("\n=== 范围查询 ===");
        System.out.println(testRange().previewSql());

        System.out.println("\n=== 模糊查询 ===");
        System.out.println(testLike().previewSql());

        // 2. 逻辑组合测试
        System.out.println("\n=== AND组合 ===");
        System.out.println(testAnd().previewSql());

        System.out.println("\n=== OR组合 ===");
        System.out.println(testOr().previewSql());

        System.out.println("\n=== 复杂逻辑混合 ===");
        System.out.println(testComplexLogic().previewSql());

        // 3. 嵌套条件测试
        System.out.println("\n=== 简单嵌套 ===");
        System.out.println(testNestedSimple().previewSql());

        System.out.println("\n=== 多层嵌套 ===");
        System.out.println(testNestedMultiLevel().previewSql());

        // 4. 集合操作测试
        System.out.println("\n=== IN查询 ===");
        System.out.println(testIn().previewSql());

        System.out.println("\n=== NOT IN查询 ===");
        System.out.println(testNotIn().previewSql());

        System.out.println("\n=== BETWEEN查询 ===");
        System.out.println(testBetween().previewSql());

        // 5. NULL值测试
        System.out.println("\n=== NULL查询 ===");
        System.out.println(testIsNull().previewSql());

        System.out.println("\n=== NOT NULL查询 ===");
//        System.out.println(testNotNull().previewSql());

        // 6. 分组排序测试
        System.out.println("\n=== 分组查询 ===");
        System.out.println(testGroupBy().previewSql());

        System.out.println("\n=== 排序查询 ===");
        System.out.println(testOrderBy().previewSql());

        // 7. 分页测试
        System.out.println("\n=== 分页查询 ===");
        System.out.println(testLimit().previewSql());

        // 8. 函数式条件测试
        System.out.println("\n=== 函数式条件 ===");
        System.out.println(testFunctional().previewSql());

        // 9. 复杂综合测试
        System.out.println("\n=== 终极综合测试 ===");
        System.out.println(testUltimate().previewSql());
    }

    // =============== 测试方法实现 ===============
    private static OpenApiLambdaWrapper<CodefyTools> testEQ() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .eq(CodefyTools::getCode, "test001")
                .eq(CodefyTools::getStatus, 1);
    }

    private static OpenApiLambdaWrapper<CodefyTools> testNE() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .ne(CodefyTools::getCode, "deleted")
                .ne(CodefyTools::getType, 99);
    }

    private static OpenApiLambdaWrapper<CodefyTools> testRange() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .gt(CodefyTools::getPrice, 100)
                .lt(CodefyTools::getPrice, 1000)
                .ge(CodefyTools::getStock, 10)
                .le(CodefyTools::getStock, 100);
    }

    private static OpenApiLambdaWrapper<CodefyTools> testLike() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .like(CodefyTools::getName, "华为")
                .likeLeft(CodefyTools::getSn, "SN2023")
                .likeRight(CodefyTools::getCode, "A");
    }

    private static OpenApiLambdaWrapper<CodefyTools> testAnd() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .eq(CodefyTools::getType, 1)
                .and()
                .gt(CodefyTools::getCreateTime, LocalDateTime.now().minusDays(7));
    }

    private static OpenApiLambdaWrapper<CodefyTools> testOr() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .eq(CodefyTools::getStatus, 1)
                .or()
                .eq(CodefyTools::getStatus, 2);
    }

    private static OpenApiLambdaWrapper<CodefyTools> testComplexLogic() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .eq(CodefyTools::getDeleted, 0)
                .and(w -> w.gt(CodefyTools::getPrice, 100).lt(CodefyTools::getPrice, 1000))
                .or(w -> w.eq(CodefyTools::getVip, 1).ge(CodefyTools::getDiscount, 0.8));
    }

    private static OpenApiLambdaWrapper<CodefyTools> testNestedSimple() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .and(w -> w.eq(CodefyTools::getType, 1).ne(CodefyTools::getStatus, 9))
                .or(w -> w.like(CodefyTools::getName, "测试").between(CodefyTools::getCreateTime,
                        LocalDateTime.now().minusDays(30), LocalDateTime.now()));
    }

    private static OpenApiLambdaWrapper<CodefyTools> testNestedMultiLevel() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .and(w1 -> w1
                        .eq(CodefyTools::getDeleted, 0)
                        .or(w2 -> w2
                                .between(CodefyTools::getPrice, 100, 500)
                                .and(w3 -> w3
                                        .like(CodefyTools::getName, "旗舰")
                                        .notIn(CodefyTools::getCategory, Arrays.asList(99, 100))
                                )
                        )
                );
    }

    private static OpenApiLambdaWrapper<CodefyTools> testIn() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .in(CodefyTools::getId, Arrays.asList(1, 2, 3))
                .in(CodefyTools::getType, new HashSet<>(Arrays.asList(10, 20)));
    }

    private static OpenApiLambdaWrapper<CodefyTools> testNotIn() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .notIn(CodefyTools::getStatus, Arrays.asList(0, 9))
                .notIn(CodefyTools::getCode, Collections.singletonList("deleted"));
    }

    private static OpenApiLambdaWrapper<CodefyTools> testBetween() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .between(CodefyTools::getCreateTime,
                        LocalDateTime.now().minusDays(7),
                        LocalDateTime.now())
                .notBetween(CodefyTools::getAge, 18, 65);
    }

    private static OpenApiLambdaWrapper<CodefyTools> testIsNull() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .isNull(CodefyTools::getDescription)
                .isNotNull(CodefyTools::getBarcode);
    }

    private static OpenApiLambdaWrapper<CodefyTools> testGroupBy() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .groupBy(CodefyTools::getCategory)
                .groupBy(CodefyTools::getBrand)
                .having(w -> w.gt(CodefyTools::getAge, 5));
    }

    private static OpenApiLambdaWrapper<CodefyTools> testOrderBy() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .orderBy(true,true, CodefyTools::getPrice)
                .orderBy(true, false, CodefyTools::getSales);
    }

    private static OpenApiLambdaWrapper<CodefyTools> testLimit() {
        return new OpenApiLambdaWrapper<CodefyTools>(CodefyTools.class)
                .limit(1, 10);
    }

    private static OpenApiLambdaWrapper<CodefyTools> testFunctional() {
        return new OpenApiLambdaWrapper<CodefyTools>();
    }

    private static OpenApiLambdaWrapper<CodefyTools> testUltimate() {
        return new OpenApiLambdaWrapper<CodefyTools>()
                .select(CodefyTools::getId, CodefyTools::getName)
                .eq(CodefyTools::getDeleted, 0)
                .and(w -> w.between(CodefyTools::getPrice, 100, 1000)
                        .or()
                        .in(CodefyTools::getCategory, Arrays.asList(3, 5, 7)
                        ))
                        .groupBy(CodefyTools::getType)
                        .having(w -> w.gt(CodefyTools::getPrice, 500))
                        .orderBy( true, true, CodefyTools::getSales)
                        .limit(1, 20);
    }
}

